﻿using System.Globalization;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using Newtonsoft.Json;

namespace Devonline.Core
{
    public static class StringExtensions
    {
        /// <summary>
        /// json 字符串转对象, 泛型用法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        public static T? ToJsonObject<T>(this string value) => JsonConvert.DeserializeObject<T>(value, AppSettings.JsonSerializerSettings);
        /// <summary>
        /// json 字符串转对象, 非泛型用法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        public static object? ToJsonObject(this string value, Type type) => JsonConvert.DeserializeObject(value, type, AppSettings.JsonSerializerSettings);

        /// <summary>
        /// 字符串是否为空或 null
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool IsNullOrEmpty(this string value) => string.IsNullOrEmpty(value);
        /// <summary>
        /// 字符串是否不为空或 null
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static bool IsNotNullOrEmpty(this string value) => !string.IsNullOrEmpty(value);
        /// <summary>
        /// 判断字符串是否无值, 既不为空也不为空格
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool IsNullOrWhiteSpace(this string value) => string.IsNullOrWhiteSpace(value);
        /// <summary>
        /// 判断字符串是否有值, 既不为空也不为空格
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool IsNotNullOrWhiteSpace(this string value) => !string.IsNullOrWhiteSpace(value);

        /// <summary>
        /// 获取文件的绝对路径
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string GetAbsolutePath(this string path) => Path.GetPathRoot(path) == null ? path : Path.Combine(AppSettings.StartupPath, path);

        /// <summary>
        /// 对字符串值按 THashAlgorithm 算法计算 Hash Code
        /// </summary>
        /// <typeparam name="THashAlgorithm">Hash 算法</typeparam>
        /// <param name="hashAlgorithm">hash 算法实例</param>
        /// <param name="value">待计算值</param>
        /// <param name="encoding">编码方式</param>
        /// <returns></returns>
        public static string GetHashCode<THashAlgorithm>(this THashAlgorithm hashAlgorithm, string value, Encoding? encoding = null) where THashAlgorithm : HashAlgorithm => Convert.ToBase64String(hashAlgorithm.ComputeHash((encoding ?? Encoding.UTF8).GetBytes(value)));
        /// <summary>
        /// 对字符串值按 THashAlgorithm 算法计算 Hash Code
        /// </summary>
        /// <typeparam name="THashAlgorithm">Hash 算法</typeparam>
        /// <param name="value">待计算值</param>
        /// <param name="encoding">编码方式</param>
        /// <returns></returns>
        public static string GetHashValue<THashAlgorithm>(this string value, Encoding? encoding = null) where THashAlgorithm : HashAlgorithm
        {
            var type = typeof(THashAlgorithm);
            using var hashAlgorithm = type.InvokeMember(nameof(HashAlgorithm.Create), BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, null, CultureInfo.CurrentCulture) as THashAlgorithm;
            if (hashAlgorithm == null)
            {
                throw new Exception($"type Hash Algorithm of {type} can't be created!");
            }

            return Convert.ToBase64String(hashAlgorithm.ComputeHash((encoding ?? Encoding.UTF8).GetBytes(value)));
        }

        /// <summary>
        /// 首字母转小写
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string FirstCharToLower(this string value)
        {
            if (value.IsNotNullOrEmpty() && char.IsUpper(value[AppSettings.UNIT_ZERO]))
            {
                return char.ToLower(value[AppSettings.UNIT_ZERO], CultureInfo.CurrentCulture) + value[1..];
            }

            return value;
        }
        /// <summary>
        /// 首字母转大写
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string FirstCharToUpper(this string value)
        {
            if (value.IsNotNullOrEmpty() && char.IsLower(value[AppSettings.UNIT_ZERO]))
            {
                return char.ToUpper(value[AppSettings.UNIT_ZERO], CultureInfo.CurrentCulture) + value[1..];
            }

            return value;
        }

        /// <summary>
        /// ping a host and then execute the action
        /// </summary>
        /// <param name="host"></param>
        /// <param name="success"></param>
        /// <param name="fail"></param>
        /// <returns></returns>
        public static async Task PingStateAsync(this string host, Action? success, Action? fail)
        {
            var ping = new Ping();
            var pingReply = await ping.SendPingAsync(host, AppSettings.UNIT_TEN * AppSettings.UNIT_THOUSAND);
            if (pingReply.Status == IPStatus.Success)
            {
                success?.Invoke();
            }
            else
            {
                fail?.Invoke();
            }
        }
    }
}